Merge 1bbc991585 ("Merge tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs") into android-mainline
Steps on the way to v6.9 Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: Ib1d162dca3e4b1793bcfba3d00f123e6a69bd2dd
This commit is contained in:
@@ -439,6 +439,7 @@ static int remove_device_files(struct super_block *sb,
|
||||
return PTR_ERR(dir);
|
||||
}
|
||||
simple_recursive_removal(dir, NULL);
|
||||
dput(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -244,10 +244,10 @@ int bch2_alloc_v4_invalid(struct bch_fs *c, struct bkey_s_c k,
|
||||
struct bkey_s_c_alloc_v4 a = bkey_s_c_to_alloc_v4(k);
|
||||
int ret = 0;
|
||||
|
||||
bkey_fsck_err_on(alloc_v4_u64s(a.v) > bkey_val_u64s(k.k), c, err,
|
||||
bkey_fsck_err_on(alloc_v4_u64s_noerror(a.v) > bkey_val_u64s(k.k), c, err,
|
||||
alloc_v4_val_size_bad,
|
||||
"bad val size (%u > %zu)",
|
||||
alloc_v4_u64s(a.v), bkey_val_u64s(k.k));
|
||||
alloc_v4_u64s_noerror(a.v), bkey_val_u64s(k.k));
|
||||
|
||||
bkey_fsck_err_on(!BCH_ALLOC_V4_BACKPOINTERS_START(a.v) &&
|
||||
BCH_ALLOC_V4_NR_BACKPOINTERS(a.v), c, err,
|
||||
|
||||
@@ -126,13 +126,17 @@ static inline struct bpos alloc_freespace_pos(struct bpos pos, struct bch_alloc_
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline unsigned alloc_v4_u64s(const struct bch_alloc_v4 *a)
|
||||
static inline unsigned alloc_v4_u64s_noerror(const struct bch_alloc_v4 *a)
|
||||
{
|
||||
unsigned ret = (BCH_ALLOC_V4_BACKPOINTERS_START(a) ?:
|
||||
return (BCH_ALLOC_V4_BACKPOINTERS_START(a) ?:
|
||||
BCH_ALLOC_V4_U64s_V0) +
|
||||
BCH_ALLOC_V4_NR_BACKPOINTERS(a) *
|
||||
(sizeof(struct bch_backpointer) / sizeof(u64));
|
||||
}
|
||||
|
||||
static inline unsigned alloc_v4_u64s(const struct bch_alloc_v4 *a)
|
||||
{
|
||||
unsigned ret = alloc_v4_u64s_noerror(a);
|
||||
BUG_ON(ret > U8_MAX - BKEY_U64s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k,
|
||||
int ret = 0;
|
||||
|
||||
bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
|
||||
!bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)),
|
||||
!bpos_eq(bp.k->p, bucket_pos_to_bp_noerror(ca, bucket, bp.v->bucket_offset)),
|
||||
c, err,
|
||||
backpointer_bucket_offset_wrong,
|
||||
"backpointer bucket_offset wrong");
|
||||
|
||||
@@ -45,6 +45,15 @@ static inline struct bpos bp_pos_to_bucket(const struct bch_fs *c,
|
||||
return POS(bp_pos.inode, sector_to_bucket(ca, bucket_sector));
|
||||
}
|
||||
|
||||
static inline struct bpos bucket_pos_to_bp_noerror(const struct bch_dev *ca,
|
||||
struct bpos bucket,
|
||||
u64 bucket_offset)
|
||||
{
|
||||
return POS(bucket.inode,
|
||||
(bucket_to_sector(ca, bucket.offset) <<
|
||||
MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert from pos in alloc btree + bucket offset to pos in backpointer btree:
|
||||
*/
|
||||
@@ -53,10 +62,7 @@ static inline struct bpos bucket_pos_to_bp(const struct bch_fs *c,
|
||||
u64 bucket_offset)
|
||||
{
|
||||
struct bch_dev *ca = bch_dev_bkey_exists(c, bucket.inode);
|
||||
struct bpos ret = POS(bucket.inode,
|
||||
(bucket_to_sector(ca, bucket.offset) <<
|
||||
MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset);
|
||||
|
||||
struct bpos ret = bucket_pos_to_bp_noerror(ca, bucket, bucket_offset);
|
||||
EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(c, ret)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -591,6 +591,12 @@ struct bch_member {
|
||||
__le64 btree_allocated_bitmap;
|
||||
};
|
||||
|
||||
/*
|
||||
* This limit comes from the bucket_gens array - it's a single allocation, and
|
||||
* kernel allocation are limited to INT_MAX
|
||||
*/
|
||||
#define BCH_MEMBER_NBUCKETS_MAX (INT_MAX - 64)
|
||||
|
||||
#define BCH_MEMBER_V1_BYTES 56
|
||||
|
||||
LE64_BITMASK(BCH_MEMBER_STATE, struct bch_member, flags, 0, 4)
|
||||
@@ -897,6 +903,8 @@ unsigned bcachefs_metadata_required_upgrade_below = bcachefs_metadata_version_re
|
||||
#define BCH_SB_SECTOR 8
|
||||
#define BCH_SB_MEMBERS_MAX 64 /* XXX kill */
|
||||
|
||||
#define BCH_SB_LAYOUT_SIZE_BITS_MAX 16 /* 32 MB */
|
||||
|
||||
struct bch_sb_layout {
|
||||
__uuid_t magic; /* bcachefs superblock UUID */
|
||||
__u8 layout_type;
|
||||
|
||||
@@ -171,8 +171,8 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
|
||||
if (type >= BKEY_TYPE_NR)
|
||||
return 0;
|
||||
|
||||
bkey_fsck_err_on((type == BKEY_TYPE_btree ||
|
||||
(flags & BKEY_INVALID_COMMIT)) &&
|
||||
bkey_fsck_err_on(k.k->type < KEY_TYPE_MAX &&
|
||||
(type == BKEY_TYPE_btree || (flags & BKEY_INVALID_COMMIT)) &&
|
||||
!(bch2_key_types_allowed[type] & BIT_ULL(k.k->type)), c, err,
|
||||
bkey_invalid_type_for_btree,
|
||||
"invalid key type for btree %s (%s)",
|
||||
|
||||
@@ -956,13 +956,15 @@ void bch2_fs_btree_key_cache_exit(struct btree_key_cache *bc)
|
||||
}
|
||||
|
||||
#ifdef __KERNEL__
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct btree_key_cache_freelist *f =
|
||||
per_cpu_ptr(bc->pcpu_freed, cpu);
|
||||
if (bc->pcpu_freed) {
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct btree_key_cache_freelist *f =
|
||||
per_cpu_ptr(bc->pcpu_freed, cpu);
|
||||
|
||||
for (i = 0; i < f->nr; i++) {
|
||||
ck = f->objs[i];
|
||||
list_add(&ck->list, &items);
|
||||
for (i = 0; i < f->nr; i++) {
|
||||
ck = f->objs[i];
|
||||
list_add(&ck->list, &items);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -102,6 +102,7 @@ static inline int do_encrypt_sg(struct crypto_sync_skcipher *tfm,
|
||||
int ret;
|
||||
|
||||
skcipher_request_set_sync_tfm(req, tfm);
|
||||
skcipher_request_set_callback(req, 0, NULL, NULL);
|
||||
skcipher_request_set_crypt(req, sg, sg, len, nonce.d);
|
||||
|
||||
ret = crypto_skcipher_encrypt(req);
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
x(EINVAL, block_size_too_small) \
|
||||
x(EINVAL, bucket_size_too_small) \
|
||||
x(EINVAL, device_size_too_small) \
|
||||
x(EINVAL, device_size_too_big) \
|
||||
x(EINVAL, device_not_a_member_of_filesystem) \
|
||||
x(EINVAL, device_has_been_removed) \
|
||||
x(EINVAL, device_splitbrain) \
|
||||
|
||||
+1
-1
@@ -964,7 +964,6 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
|
||||
struct btree_iter iter;
|
||||
struct bkey_s_c k;
|
||||
struct bkey_buf cur, prev;
|
||||
struct bpos end = POS(ei->v.i_ino, (start + len) >> 9);
|
||||
unsigned offset_into_extent, sectors;
|
||||
bool have_extent = false;
|
||||
u32 snapshot;
|
||||
@@ -974,6 +973,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
struct bpos end = POS(ei->v.i_ino, (start + len) >> 9);
|
||||
if (start + len < start)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
+20
-10
@@ -199,9 +199,6 @@ static inline int bch2_extent_update_i_size_sectors(struct btree_trans *trans,
|
||||
u64 new_i_size,
|
||||
s64 i_sectors_delta)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
struct bkey_i *k;
|
||||
struct bkey_i_inode_v3 *inode;
|
||||
/*
|
||||
* Crazy performance optimization:
|
||||
* Every extent update needs to also update the inode: the inode trigger
|
||||
@@ -214,25 +211,36 @@ static inline int bch2_extent_update_i_size_sectors(struct btree_trans *trans,
|
||||
* lost, but that's fine.
|
||||
*/
|
||||
unsigned inode_update_flags = BTREE_UPDATE_NOJOURNAL;
|
||||
int ret;
|
||||
|
||||
k = bch2_bkey_get_mut_noupdate(trans, &iter, BTREE_ID_inodes,
|
||||
struct btree_iter iter;
|
||||
struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
|
||||
SPOS(0,
|
||||
extent_iter->pos.inode,
|
||||
extent_iter->snapshot),
|
||||
BTREE_ITER_CACHED);
|
||||
ret = PTR_ERR_OR_ZERO(k);
|
||||
int ret = bkey_err(k);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
if (unlikely(k->k.type != KEY_TYPE_inode_v3)) {
|
||||
k = bch2_inode_to_v3(trans, k);
|
||||
ret = PTR_ERR_OR_ZERO(k);
|
||||
/*
|
||||
* varint_decode_fast(), in the inode .invalid method, reads up to 7
|
||||
* bytes past the end of the buffer:
|
||||
*/
|
||||
struct bkey_i *k_mut = bch2_trans_kmalloc_nomemzero(trans, bkey_bytes(k.k) + 8);
|
||||
ret = PTR_ERR_OR_ZERO(k_mut);
|
||||
if (unlikely(ret))
|
||||
goto err;
|
||||
|
||||
bkey_reassemble(k_mut, k);
|
||||
|
||||
if (unlikely(k_mut->k.type != KEY_TYPE_inode_v3)) {
|
||||
k_mut = bch2_inode_to_v3(trans, k_mut);
|
||||
ret = PTR_ERR_OR_ZERO(k_mut);
|
||||
if (unlikely(ret))
|
||||
goto err;
|
||||
}
|
||||
|
||||
inode = bkey_i_to_inode_v3(k);
|
||||
struct bkey_i_inode_v3 *inode = bkey_i_to_inode_v3(k_mut);
|
||||
|
||||
if (!(le64_to_cpu(inode->v.bi_flags) & BCH_INODE_i_size_dirty) &&
|
||||
new_i_size > le64_to_cpu(inode->v.bi_size)) {
|
||||
@@ -1505,6 +1513,8 @@ static void bch2_write_data_inline(struct bch_write_op *op, unsigned data_len)
|
||||
unsigned sectors;
|
||||
int ret;
|
||||
|
||||
memset(&op->failed, 0, sizeof(op->failed));
|
||||
|
||||
op->flags |= BCH_WRITE_WROTE_DATA_INLINE;
|
||||
op->flags |= BCH_WRITE_DONE;
|
||||
|
||||
|
||||
@@ -706,6 +706,12 @@ recheck_need_open:
|
||||
|
||||
spin_unlock(&j->lock);
|
||||
|
||||
/*
|
||||
* We're called from bch2_journal_flush_seq() -> wait_event();
|
||||
* but this might block. We won't usually block, so we won't
|
||||
* livelock:
|
||||
*/
|
||||
sched_annotate_sleep();
|
||||
ret = bch2_journal_res_get(j, &res, jset_u64s(0), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -870,6 +876,8 @@ static struct journal_buf *__bch2_next_write_buffer_flush_journal_buf(struct jou
|
||||
{
|
||||
struct journal_buf *ret = NULL;
|
||||
|
||||
/* We're inside wait_event(), but using mutex_lock(: */
|
||||
sched_annotate_sleep();
|
||||
mutex_lock(&j->buf_lock);
|
||||
spin_lock(&j->lock);
|
||||
max_seq = min(max_seq, journal_cur_seq(j));
|
||||
|
||||
+14
-8
@@ -968,24 +968,30 @@ static bool migrate_btree_pred(struct bch_fs *c, void *arg,
|
||||
return migrate_pred(c, arg, bkey_i_to_s_c(&b->key), io_opts, data_opts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ancient versions of bcachefs produced packed formats which could represent
|
||||
* keys that the in memory format cannot represent; this checks for those
|
||||
* formats so we can get rid of them.
|
||||
*/
|
||||
static bool bformat_needs_redo(struct bkey_format *f)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < f->nr_fields; i++) {
|
||||
for (unsigned i = 0; i < f->nr_fields; i++) {
|
||||
unsigned f_bits = f->bits_per_field[i];
|
||||
unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
|
||||
u64 unpacked_mask = ~((~0ULL << 1) << (unpacked_bits - 1));
|
||||
u64 field_offset = le64_to_cpu(f->field_offset[i]);
|
||||
|
||||
if (f->bits_per_field[i] > unpacked_bits)
|
||||
if (f_bits > unpacked_bits)
|
||||
return true;
|
||||
|
||||
if ((f->bits_per_field[i] == unpacked_bits) && field_offset)
|
||||
if ((f_bits == unpacked_bits) && field_offset)
|
||||
return true;
|
||||
|
||||
if (((field_offset + ((1ULL << f->bits_per_field[i]) - 1)) &
|
||||
unpacked_mask) <
|
||||
field_offset)
|
||||
u64 f_mask = f_bits
|
||||
? ~((~0ULL << (f_bits - 1)) << 1)
|
||||
: 0;
|
||||
|
||||
if (((field_offset + f_mask) & unpacked_mask) < field_offset)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -560,13 +560,11 @@ static int bch2_fs_quota_read_inode(struct btree_trans *trans,
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bch_inode_unpacked u;
|
||||
struct bch_snapshot_tree s_t;
|
||||
int ret;
|
||||
u32 tree = bch2_snapshot_tree(c, k.k->p.snapshot);
|
||||
|
||||
ret = bch2_snapshot_tree_lookup(trans,
|
||||
bch2_snapshot_tree(c, k.k->p.snapshot), &s_t);
|
||||
int ret = bch2_snapshot_tree_lookup(trans, tree, &s_t);
|
||||
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
|
||||
"%s: snapshot tree %u not found", __func__,
|
||||
snapshot_t(c, k.k->p.snapshot)->tree);
|
||||
"%s: snapshot tree %u not found", __func__, tree);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -902,7 +902,8 @@ out:
|
||||
bch2_journal_keys_put_initial(c);
|
||||
bch2_find_btree_nodes_exit(&c->found_btree_nodes);
|
||||
}
|
||||
kfree(clean);
|
||||
if (!IS_ERR(clean))
|
||||
kfree(clean);
|
||||
|
||||
if (!ret &&
|
||||
test_bit(BCH_FS_need_delete_dead_snapshots, &c->flags) &&
|
||||
|
||||
@@ -278,6 +278,17 @@ static int bch2_sb_clean_validate(struct bch_sb *sb,
|
||||
return -BCH_ERR_invalid_sb_clean;
|
||||
}
|
||||
|
||||
for (struct jset_entry *entry = clean->start;
|
||||
entry != vstruct_end(&clean->field);
|
||||
entry = vstruct_next(entry)) {
|
||||
if ((void *) vstruct_next(entry) > vstruct_end(&clean->field)) {
|
||||
prt_str(err, "entry type ");
|
||||
bch2_prt_jset_entry_type(err, le16_to_cpu(entry->type));
|
||||
prt_str(err, " overruns end of section");
|
||||
return -BCH_ERR_invalid_sb_clean;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -295,6 +306,9 @@ static void bch2_sb_clean_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||
for (entry = clean->start;
|
||||
entry != vstruct_end(&clean->field);
|
||||
entry = vstruct_next(entry)) {
|
||||
if ((void *) vstruct_next(entry) > vstruct_end(&clean->field))
|
||||
break;
|
||||
|
||||
if (entry->type == BCH_JSET_ENTRY_btree_keys &&
|
||||
!entry->u64s)
|
||||
continue;
|
||||
|
||||
@@ -124,9 +124,9 @@ static int validate_member(struct printbuf *err,
|
||||
struct bch_sb *sb,
|
||||
int i)
|
||||
{
|
||||
if (le64_to_cpu(m.nbuckets) > LONG_MAX) {
|
||||
prt_printf(err, "device %u: too many buckets (got %llu, max %lu)",
|
||||
i, le64_to_cpu(m.nbuckets), LONG_MAX);
|
||||
if (le64_to_cpu(m.nbuckets) > BCH_MEMBER_NBUCKETS_MAX) {
|
||||
prt_printf(err, "device %u: too many buckets (got %llu, max %u)",
|
||||
i, le64_to_cpu(m.nbuckets), BCH_MEMBER_NBUCKETS_MAX);
|
||||
return -BCH_ERR_invalid_sb_members;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,10 +107,10 @@ static inline struct bch_dev *__bch2_next_dev(struct bch_fs *c, struct bch_dev *
|
||||
|
||||
static inline struct bch_dev *bch2_get_next_dev(struct bch_fs *c, struct bch_dev *ca)
|
||||
{
|
||||
rcu_read_lock();
|
||||
if (ca)
|
||||
percpu_ref_put(&ca->ref);
|
||||
|
||||
rcu_read_lock();
|
||||
if ((ca = __bch2_next_dev(c, ca, NULL)))
|
||||
percpu_ref_get(&ca->ref);
|
||||
rcu_read_unlock();
|
||||
@@ -132,10 +132,10 @@ static inline struct bch_dev *bch2_get_next_online_dev(struct bch_fs *c,
|
||||
struct bch_dev *ca,
|
||||
unsigned state_mask)
|
||||
{
|
||||
rcu_read_lock();
|
||||
if (ca)
|
||||
percpu_ref_put(&ca->io_ref);
|
||||
|
||||
rcu_read_lock();
|
||||
while ((ca = __bch2_next_dev(c, ca, NULL)) &&
|
||||
(!((1 << ca->mi.state) & state_mask) ||
|
||||
!percpu_ref_tryget(&ca->io_ref)))
|
||||
|
||||
+34
-17
@@ -232,7 +232,7 @@ struct bch_sb_field *bch2_sb_field_resize_id(struct bch_sb_handle *sb,
|
||||
struct bch_sb_handle *dev_sb = &ca->disk_sb;
|
||||
|
||||
if (bch2_sb_realloc(dev_sb, le32_to_cpu(dev_sb->sb->u64s) + d)) {
|
||||
percpu_ref_put(&ca->ref);
|
||||
percpu_ref_put(&ca->io_ref);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -649,7 +649,7 @@ reread:
|
||||
|
||||
bytes = vstruct_bytes(sb->sb);
|
||||
|
||||
if (bytes > 512 << sb->sb->layout.sb_max_size_bits) {
|
||||
if (bytes > 512ULL << min(BCH_SB_LAYOUT_SIZE_BITS_MAX, sb->sb->layout.sb_max_size_bits)) {
|
||||
prt_printf(err, "Invalid superblock: too big (got %zu bytes, layout max %lu)",
|
||||
bytes, 512UL << sb->sb->layout.sb_max_size_bits);
|
||||
return -BCH_ERR_invalid_sb_too_big;
|
||||
@@ -923,6 +923,7 @@ int bch2_write_super(struct bch_fs *c)
|
||||
struct bch_devs_mask sb_written;
|
||||
bool wrote, can_mount_without_written, can_mount_with_written;
|
||||
unsigned degraded_flags = BCH_FORCE_IF_DEGRADED;
|
||||
DARRAY(struct bch_dev *) online_devices = {};
|
||||
int ret = 0;
|
||||
|
||||
trace_and_count(c, write_super, c, _RET_IP_);
|
||||
@@ -935,6 +936,15 @@ int bch2_write_super(struct bch_fs *c)
|
||||
closure_init_stack(cl);
|
||||
memset(&sb_written, 0, sizeof(sb_written));
|
||||
|
||||
for_each_online_member(c, ca) {
|
||||
ret = darray_push(&online_devices, ca);
|
||||
if (bch2_fs_fatal_err_on(ret, c, "%s: error allocating online devices", __func__)) {
|
||||
percpu_ref_put(&ca->io_ref);
|
||||
goto out;
|
||||
}
|
||||
percpu_ref_get(&ca->io_ref);
|
||||
}
|
||||
|
||||
/* Make sure we're using the new magic numbers: */
|
||||
c->disk_sb.sb->magic = BCHFS_MAGIC;
|
||||
c->disk_sb.sb->layout.magic = BCHFS_MAGIC;
|
||||
@@ -942,8 +952,8 @@ int bch2_write_super(struct bch_fs *c)
|
||||
le64_add_cpu(&c->disk_sb.sb->seq, 1);
|
||||
|
||||
struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
|
||||
for_each_online_member(c, ca)
|
||||
__bch2_members_v2_get_mut(mi, ca->dev_idx)->seq = c->disk_sb.sb->seq;
|
||||
darray_for_each(online_devices, ca)
|
||||
__bch2_members_v2_get_mut(mi, (*ca)->dev_idx)->seq = c->disk_sb.sb->seq;
|
||||
c->disk_sb.sb->write_time = cpu_to_le64(ktime_get_real_seconds());
|
||||
|
||||
if (test_bit(BCH_FS_error, &c->flags))
|
||||
@@ -959,16 +969,15 @@ int bch2_write_super(struct bch_fs *c)
|
||||
bch2_sb_errors_from_cpu(c);
|
||||
bch2_sb_downgrade_update(c);
|
||||
|
||||
for_each_online_member(c, ca)
|
||||
bch2_sb_from_fs(c, ca);
|
||||
darray_for_each(online_devices, ca)
|
||||
bch2_sb_from_fs(c, (*ca));
|
||||
|
||||
for_each_online_member(c, ca) {
|
||||
darray_for_each(online_devices, ca) {
|
||||
printbuf_reset(&err);
|
||||
|
||||
ret = bch2_sb_validate(&ca->disk_sb, &err, WRITE);
|
||||
ret = bch2_sb_validate(&(*ca)->disk_sb, &err, WRITE);
|
||||
if (ret) {
|
||||
bch2_fs_inconsistent(c, "sb invalid before write: %s", err.buf);
|
||||
percpu_ref_put(&ca->io_ref);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -995,16 +1004,18 @@ int bch2_write_super(struct bch_fs *c)
|
||||
return -BCH_ERR_sb_not_downgraded;
|
||||
}
|
||||
|
||||
for_each_online_member(c, ca) {
|
||||
__set_bit(ca->dev_idx, sb_written.d);
|
||||
ca->sb_write_error = 0;
|
||||
darray_for_each(online_devices, ca) {
|
||||
__set_bit((*ca)->dev_idx, sb_written.d);
|
||||
(*ca)->sb_write_error = 0;
|
||||
}
|
||||
|
||||
for_each_online_member(c, ca)
|
||||
read_back_super(c, ca);
|
||||
darray_for_each(online_devices, ca)
|
||||
read_back_super(c, *ca);
|
||||
closure_sync(cl);
|
||||
|
||||
for_each_online_member(c, ca) {
|
||||
darray_for_each(online_devices, cap) {
|
||||
struct bch_dev *ca = *cap;
|
||||
|
||||
if (ca->sb_write_error)
|
||||
continue;
|
||||
|
||||
@@ -1031,17 +1042,20 @@ int bch2_write_super(struct bch_fs *c)
|
||||
|
||||
do {
|
||||
wrote = false;
|
||||
for_each_online_member(c, ca)
|
||||
darray_for_each(online_devices, cap) {
|
||||
struct bch_dev *ca = *cap;
|
||||
if (!ca->sb_write_error &&
|
||||
sb < ca->disk_sb.sb->layout.nr_superblocks) {
|
||||
write_one_super(c, ca, sb);
|
||||
wrote = true;
|
||||
}
|
||||
}
|
||||
closure_sync(cl);
|
||||
sb++;
|
||||
} while (wrote);
|
||||
|
||||
for_each_online_member(c, ca) {
|
||||
darray_for_each(online_devices, cap) {
|
||||
struct bch_dev *ca = *cap;
|
||||
if (ca->sb_write_error)
|
||||
__clear_bit(ca->dev_idx, sb_written.d);
|
||||
else
|
||||
@@ -1077,6 +1091,9 @@ int bch2_write_super(struct bch_fs *c)
|
||||
out:
|
||||
/* Make new options visible after they're persistent: */
|
||||
bch2_sb_update(c);
|
||||
darray_for_each(online_devices, ca)
|
||||
percpu_ref_put(&(*ca)->io_ref);
|
||||
darray_exit(&online_devices);
|
||||
printbuf_exit(&err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+9
-6
@@ -1959,6 +1959,13 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (nbuckets > BCH_MEMBER_NBUCKETS_MAX) {
|
||||
bch_err(ca, "New device size too big (%llu greater than max %u)",
|
||||
nbuckets, BCH_MEMBER_NBUCKETS_MAX);
|
||||
ret = -BCH_ERR_device_size_too_big;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (bch2_dev_is_online(ca) &&
|
||||
get_capacity(ca->disk_sb.bdev->bd_disk) <
|
||||
ca->mi.bucket_size * nbuckets) {
|
||||
@@ -2004,13 +2011,9 @@ err:
|
||||
/* return with ref on ca->ref: */
|
||||
struct bch_dev *bch2_dev_lookup(struct bch_fs *c, const char *name)
|
||||
{
|
||||
rcu_read_lock();
|
||||
for_each_member_device_rcu(c, ca, NULL)
|
||||
if (!strcmp(name, ca->name)) {
|
||||
rcu_read_unlock();
|
||||
for_each_member_device(c, ca)
|
||||
if (!strcmp(name, ca->name))
|
||||
return ca;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return ERR_PTR(-BCH_ERR_ENOENT_dev_not_found);
|
||||
}
|
||||
|
||||
|
||||
@@ -420,6 +420,7 @@ static void exfat_set_entry_type(struct exfat_dentry *ep, unsigned int type)
|
||||
static void exfat_init_stream_entry(struct exfat_dentry *ep,
|
||||
unsigned int start_clu, unsigned long long size)
|
||||
{
|
||||
memset(ep, 0, sizeof(*ep));
|
||||
exfat_set_entry_type(ep, TYPE_STREAM);
|
||||
if (size == 0)
|
||||
ep->dentry.stream.flags = ALLOC_FAT_CHAIN;
|
||||
@@ -457,6 +458,7 @@ void exfat_init_dir_entry(struct exfat_entry_set_cache *es,
|
||||
struct exfat_dentry *ep;
|
||||
|
||||
ep = exfat_get_dentry_cached(es, ES_IDX_FILE);
|
||||
memset(ep, 0, sizeof(*ep));
|
||||
exfat_set_entry_type(ep, type);
|
||||
exfat_set_entry_time(sbi, ts,
|
||||
&ep->dentry.file.create_tz,
|
||||
|
||||
+4
-5
@@ -51,7 +51,7 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
|
||||
clu.flags = ei->flags;
|
||||
|
||||
ret = exfat_alloc_cluster(inode, new_num_clusters - num_clusters,
|
||||
&clu, IS_DIRSYNC(inode));
|
||||
&clu, inode_needs_sync(inode));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -77,12 +77,11 @@ out:
|
||||
ei->i_size_aligned = round_up(size, sb->s_blocksize);
|
||||
ei->i_size_ondisk = ei->i_size_aligned;
|
||||
inode->i_blocks = round_up(size, sbi->cluster_size) >> 9;
|
||||
|
||||
if (IS_DIRSYNC(inode))
|
||||
return write_inode_now(inode, 1);
|
||||
|
||||
mark_inode_dirty(inode);
|
||||
|
||||
if (IS_SYNC(inode))
|
||||
return write_inode_now(inode, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
free_clu:
|
||||
|
||||
@@ -225,7 +225,7 @@ int fuse_backing_open(struct fuse_conn *fc, struct fuse_backing_map *map)
|
||||
goto out;
|
||||
|
||||
res = -EINVAL;
|
||||
if (map->flags)
|
||||
if (map->flags || map->padding)
|
||||
goto out;
|
||||
|
||||
file = fget(map->fd);
|
||||
|
||||
+1
-1
@@ -170,7 +170,7 @@ static ssize_t tag_show(struct kobject *kobj,
|
||||
{
|
||||
struct virtio_fs *fs = container_of(kobj, struct virtio_fs, kobj);
|
||||
|
||||
return sysfs_emit(buf, fs->tag);
|
||||
return sysfs_emit(buf, "%s\n", fs->tag);
|
||||
}
|
||||
|
||||
static struct kobj_attribute virtio_fs_tag_attr = __ATTR_RO(tag);
|
||||
|
||||
+35
-30
@@ -207,9 +207,9 @@ static void opinfo_add(struct oplock_info *opinfo)
|
||||
{
|
||||
struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
|
||||
|
||||
write_lock(&ci->m_lock);
|
||||
down_write(&ci->m_lock);
|
||||
list_add_rcu(&opinfo->op_entry, &ci->m_op_list);
|
||||
write_unlock(&ci->m_lock);
|
||||
up_write(&ci->m_lock);
|
||||
}
|
||||
|
||||
static void opinfo_del(struct oplock_info *opinfo)
|
||||
@@ -221,9 +221,9 @@ static void opinfo_del(struct oplock_info *opinfo)
|
||||
lease_del_list(opinfo);
|
||||
write_unlock(&lease_list_lock);
|
||||
}
|
||||
write_lock(&ci->m_lock);
|
||||
down_write(&ci->m_lock);
|
||||
list_del_rcu(&opinfo->op_entry);
|
||||
write_unlock(&ci->m_lock);
|
||||
up_write(&ci->m_lock);
|
||||
}
|
||||
|
||||
static unsigned long opinfo_count(struct ksmbd_file *fp)
|
||||
@@ -526,21 +526,18 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
|
||||
* Compare lease key and client_guid to know request from same owner
|
||||
* of same client
|
||||
*/
|
||||
read_lock(&ci->m_lock);
|
||||
down_read(&ci->m_lock);
|
||||
list_for_each_entry(opinfo, &ci->m_op_list, op_entry) {
|
||||
if (!opinfo->is_lease || !opinfo->conn)
|
||||
continue;
|
||||
read_unlock(&ci->m_lock);
|
||||
lease = opinfo->o_lease;
|
||||
|
||||
ret = compare_guid_key(opinfo, client_guid, lctx->lease_key);
|
||||
if (ret) {
|
||||
m_opinfo = opinfo;
|
||||
/* skip upgrading lease about breaking lease */
|
||||
if (atomic_read(&opinfo->breaking_cnt)) {
|
||||
read_lock(&ci->m_lock);
|
||||
if (atomic_read(&opinfo->breaking_cnt))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* upgrading lease */
|
||||
if ((atomic_read(&ci->op_count) +
|
||||
@@ -570,9 +567,8 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
|
||||
lease_none_upgrade(opinfo, lctx->req_state);
|
||||
}
|
||||
}
|
||||
read_lock(&ci->m_lock);
|
||||
}
|
||||
read_unlock(&ci->m_lock);
|
||||
up_read(&ci->m_lock);
|
||||
|
||||
return m_opinfo;
|
||||
}
|
||||
@@ -613,13 +609,23 @@ static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
|
||||
|
||||
if (opinfo->op_state == OPLOCK_CLOSING)
|
||||
return -ENOENT;
|
||||
else if (!opinfo->is_lease && opinfo->level <= req_op_level)
|
||||
return 1;
|
||||
else if (opinfo->level <= req_op_level) {
|
||||
if (opinfo->is_lease &&
|
||||
opinfo->o_lease->state !=
|
||||
(SMB2_LEASE_HANDLE_CACHING_LE |
|
||||
SMB2_LEASE_READ_CACHING_LE))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!opinfo->is_lease && opinfo->level <= req_op_level) {
|
||||
wake_up_oplock_break(opinfo);
|
||||
return 1;
|
||||
if (opinfo->level <= req_op_level) {
|
||||
if (opinfo->is_lease &&
|
||||
opinfo->o_lease->state !=
|
||||
(SMB2_LEASE_HANDLE_CACHING_LE |
|
||||
SMB2_LEASE_READ_CACHING_LE)) {
|
||||
wake_up_oplock_break(opinfo);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -887,7 +893,6 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level)
|
||||
struct lease *lease = brk_opinfo->o_lease;
|
||||
|
||||
atomic_inc(&brk_opinfo->breaking_cnt);
|
||||
|
||||
err = oplock_break_pending(brk_opinfo, req_op_level);
|
||||
if (err)
|
||||
return err < 0 ? err : 0;
|
||||
@@ -1105,7 +1110,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
|
||||
if (!p_ci)
|
||||
return;
|
||||
|
||||
read_lock(&p_ci->m_lock);
|
||||
down_read(&p_ci->m_lock);
|
||||
list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
|
||||
if (opinfo->conn == NULL || !opinfo->is_lease)
|
||||
continue;
|
||||
@@ -1123,13 +1128,11 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
|
||||
continue;
|
||||
}
|
||||
|
||||
read_unlock(&p_ci->m_lock);
|
||||
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
|
||||
opinfo_conn_put(opinfo);
|
||||
read_lock(&p_ci->m_lock);
|
||||
}
|
||||
}
|
||||
read_unlock(&p_ci->m_lock);
|
||||
up_read(&p_ci->m_lock);
|
||||
|
||||
ksmbd_inode_put(p_ci);
|
||||
}
|
||||
@@ -1150,7 +1153,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
|
||||
if (!p_ci)
|
||||
return;
|
||||
|
||||
read_lock(&p_ci->m_lock);
|
||||
down_read(&p_ci->m_lock);
|
||||
list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
|
||||
if (opinfo->conn == NULL || !opinfo->is_lease)
|
||||
continue;
|
||||
@@ -1164,13 +1167,11 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
|
||||
atomic_dec(&opinfo->conn->r_count);
|
||||
continue;
|
||||
}
|
||||
read_unlock(&p_ci->m_lock);
|
||||
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
|
||||
opinfo_conn_put(opinfo);
|
||||
read_lock(&p_ci->m_lock);
|
||||
}
|
||||
}
|
||||
read_unlock(&p_ci->m_lock);
|
||||
up_read(&p_ci->m_lock);
|
||||
|
||||
ksmbd_inode_put(p_ci);
|
||||
}
|
||||
@@ -1200,7 +1201,9 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
|
||||
|
||||
/* Only v2 leases handle the directory */
|
||||
if (S_ISDIR(file_inode(fp->filp)->i_mode)) {
|
||||
if (!lctx || lctx->version != 2)
|
||||
if (!lctx || lctx->version != 2 ||
|
||||
(lctx->flags != SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE &&
|
||||
!lctx->epoch))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1465,8 +1468,9 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
|
||||
buf->lcontext.LeaseFlags = lease->flags;
|
||||
buf->lcontext.Epoch = cpu_to_le16(lease->epoch);
|
||||
buf->lcontext.LeaseState = lease->state;
|
||||
memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
if (lease->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)
|
||||
memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
buf->ccontext.DataOffset = cpu_to_le16(offsetof
|
||||
(struct create_lease_v2, lcontext));
|
||||
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
|
||||
@@ -1525,8 +1529,9 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
|
||||
lreq->flags = lc->lcontext.LeaseFlags;
|
||||
lreq->epoch = lc->lcontext.Epoch;
|
||||
lreq->duration = lc->lcontext.LeaseDuration;
|
||||
memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
if (lreq->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)
|
||||
memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
lreq->version = 2;
|
||||
} else {
|
||||
struct create_lease *lc = (struct create_lease *)cc;
|
||||
|
||||
@@ -1926,7 +1926,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
|
||||
struct ksmbd_session *sess = work->sess;
|
||||
char *treename = NULL, *name = NULL;
|
||||
struct ksmbd_tree_conn_status status;
|
||||
struct ksmbd_share_config *share;
|
||||
struct ksmbd_share_config *share = NULL;
|
||||
int rc = -EINVAL;
|
||||
|
||||
WORK_BUFFERS(work, req, rsp);
|
||||
@@ -1988,7 +1988,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
|
||||
write_unlock(&sess->tree_conns_lock);
|
||||
rsp->StructureSize = cpu_to_le16(16);
|
||||
out_err1:
|
||||
if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE &&
|
||||
if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE && share &&
|
||||
test_share_config_flag(share,
|
||||
KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
|
||||
rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
|
||||
@@ -3376,9 +3376,9 @@ int smb2_open(struct ksmbd_work *work)
|
||||
* after daccess, saccess, attrib_only, and stream are
|
||||
* initialized.
|
||||
*/
|
||||
write_lock(&fp->f_ci->m_lock);
|
||||
down_write(&fp->f_ci->m_lock);
|
||||
list_add(&fp->node, &fp->f_ci->m_fp_list);
|
||||
write_unlock(&fp->f_ci->m_lock);
|
||||
up_write(&fp->f_ci->m_lock);
|
||||
|
||||
/* Check delete pending among previous fp before oplock break */
|
||||
if (ksmbd_inode_pending_delete(fp)) {
|
||||
|
||||
@@ -646,7 +646,7 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
|
||||
* Lookup fp in master fp list, and check desired access and
|
||||
* shared mode between previous open and current open.
|
||||
*/
|
||||
read_lock(&curr_fp->f_ci->m_lock);
|
||||
down_read(&curr_fp->f_ci->m_lock);
|
||||
list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) {
|
||||
if (file_inode(filp) != file_inode(prev_fp->filp))
|
||||
continue;
|
||||
@@ -722,7 +722,7 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock(&curr_fp->f_ci->m_lock);
|
||||
up_read(&curr_fp->f_ci->m_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -448,6 +448,10 @@ static int create_socket(struct interface *iface)
|
||||
sin6.sin6_family = PF_INET6;
|
||||
sin6.sin6_addr = in6addr_any;
|
||||
sin6.sin6_port = htons(server_conf.tcp_port);
|
||||
|
||||
lock_sock(ksmbd_socket->sk);
|
||||
ksmbd_socket->sk->sk_ipv6only = false;
|
||||
release_sock(ksmbd_socket->sk);
|
||||
}
|
||||
|
||||
ksmbd_tcp_nodelay(ksmbd_socket);
|
||||
|
||||
+14
-14
@@ -165,7 +165,7 @@ static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
|
||||
ci->m_fattr = 0;
|
||||
INIT_LIST_HEAD(&ci->m_fp_list);
|
||||
INIT_LIST_HEAD(&ci->m_op_list);
|
||||
rwlock_init(&ci->m_lock);
|
||||
init_rwsem(&ci->m_lock);
|
||||
ci->m_de = fp->filp->f_path.dentry;
|
||||
return 0;
|
||||
}
|
||||
@@ -261,14 +261,14 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
|
||||
}
|
||||
|
||||
if (atomic_dec_and_test(&ci->m_count)) {
|
||||
write_lock(&ci->m_lock);
|
||||
down_write(&ci->m_lock);
|
||||
if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
|
||||
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
|
||||
write_unlock(&ci->m_lock);
|
||||
up_write(&ci->m_lock);
|
||||
ksmbd_vfs_unlink(filp);
|
||||
write_lock(&ci->m_lock);
|
||||
down_write(&ci->m_lock);
|
||||
}
|
||||
write_unlock(&ci->m_lock);
|
||||
up_write(&ci->m_lock);
|
||||
|
||||
ksmbd_inode_free(ci);
|
||||
}
|
||||
@@ -289,9 +289,9 @@ static void __ksmbd_remove_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp
|
||||
if (!has_file_id(fp->volatile_id))
|
||||
return;
|
||||
|
||||
write_lock(&fp->f_ci->m_lock);
|
||||
down_write(&fp->f_ci->m_lock);
|
||||
list_del_init(&fp->node);
|
||||
write_unlock(&fp->f_ci->m_lock);
|
||||
up_write(&fp->f_ci->m_lock);
|
||||
|
||||
write_lock(&ft->lock);
|
||||
idr_remove(ft->idr, fp->volatile_id);
|
||||
@@ -523,17 +523,17 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry)
|
||||
if (!ci)
|
||||
return NULL;
|
||||
|
||||
read_lock(&ci->m_lock);
|
||||
down_read(&ci->m_lock);
|
||||
list_for_each_entry(lfp, &ci->m_fp_list, node) {
|
||||
if (inode == file_inode(lfp->filp)) {
|
||||
atomic_dec(&ci->m_count);
|
||||
lfp = ksmbd_fp_get(lfp);
|
||||
read_unlock(&ci->m_lock);
|
||||
up_read(&ci->m_lock);
|
||||
return lfp;
|
||||
}
|
||||
}
|
||||
atomic_dec(&ci->m_count);
|
||||
read_unlock(&ci->m_lock);
|
||||
up_read(&ci->m_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -705,13 +705,13 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon,
|
||||
|
||||
conn = fp->conn;
|
||||
ci = fp->f_ci;
|
||||
write_lock(&ci->m_lock);
|
||||
down_write(&ci->m_lock);
|
||||
list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
|
||||
if (op->conn != conn)
|
||||
continue;
|
||||
op->conn = NULL;
|
||||
}
|
||||
write_unlock(&ci->m_lock);
|
||||
up_write(&ci->m_lock);
|
||||
|
||||
fp->conn = NULL;
|
||||
fp->tcon = NULL;
|
||||
@@ -801,13 +801,13 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
|
||||
fp->tcon = work->tcon;
|
||||
|
||||
ci = fp->f_ci;
|
||||
write_lock(&ci->m_lock);
|
||||
down_write(&ci->m_lock);
|
||||
list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
|
||||
if (op->conn)
|
||||
continue;
|
||||
op->conn = fp->conn;
|
||||
}
|
||||
write_unlock(&ci->m_lock);
|
||||
up_write(&ci->m_lock);
|
||||
|
||||
__open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
|
||||
if (!has_file_id(fp->volatile_id)) {
|
||||
|
||||
@@ -47,7 +47,7 @@ struct stream {
|
||||
};
|
||||
|
||||
struct ksmbd_inode {
|
||||
rwlock_t m_lock;
|
||||
struct rw_semaphore m_lock;
|
||||
atomic_t m_count;
|
||||
atomic_t op_count;
|
||||
/* opinfo count for streams */
|
||||
|
||||
Reference in New Issue
Block a user