Re: [PATCH v2 2/3] nilfs2: add nilfs_sufile_set_suinfo to update segment usage info

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2014-01-24 12:56, Ryusuke Konishi wrote:
> On Tue, 21 Jan 2014 15:00:29 +0100, Andreas Rohner wrote:
>> This patch introduces the nilfs_sufile_set_suinfo function, which
>> expects an array of nilfs_suinfo_update structures and updates the
>> segment usage information accordingly.
>>
>> This is basically a helper function for the newly introduced
>> NILFS_IOCTL_SET_SUINFO ioctl.
>>
>> Signed-off-by: Andreas Rohner <andreas.rohner@xxxxxxx>
>> ---
>>  fs/nilfs2/sufile.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  fs/nilfs2/sufile.h |  2 +-
>>  2 files changed, 92 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
>> index 3127e9f..81c3438 100644
>> --- a/fs/nilfs2/sufile.c
>> +++ b/fs/nilfs2/sufile.c
>> @@ -870,6 +870,97 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
>>  }
>>  
>>  /**
>> + * nilfs_sufile_set_suinfo -
> 
> Please fill the summary line of function even though
> nilfs_sufile_get_suinfo() function lacks it.
> 
>  * nilfs_sufile_set_suinfo - update segment usage information
> 
>> + * @sufile: inode of segment usage file
>> + * @buf: array of suinfo
>> + * @supsz: byte size of suinfo
>> + * @nsup: size of suinfo array
>> + *
>> + * Description: Takes an array of nilfs_suinfo_update structs and updates
>> + * segment usage accordingly.
>> + *
>> + * Return Value: On success, 0 is returned and .... On error, one of the
>> + * following negative error codes is returned.
>> + *
>> + * %-EIO - I/O error.
>> + *
>> + * %-ENOMEM - Insufficient amount of memory available.
>> + *
>> + * %-EINVAL - Invalid segment number in input
>> + */
>> +ssize_t nilfs_sufile_set_suinfo(struct inode *sufile, void *buf,
>> +				unsigned supsz, size_t nsup)
>> +{
>> +	struct buffer_head *bh;
>> +	struct nilfs_suinfo_update *sup, *supv = buf;
>> +	struct nilfs_segment_usage *su;
>> +	void *kaddr;
>> +	unsigned long blkoff, prev_blkoff;
>> +	size_t nerr = 0;
>> +	int ret = 0;
>> +
>> +	if (unlikely(nsup == 0))
>> +		goto out;
>> +
>> +	down_write(&NILFS_MDT(sufile)->mi_sem);
>> +	for (sup = supv; sup < supv + nsup; sup++) {
>> +		if (unlikely(sup->sup_segnum >=
>> +				nilfs_sufile_get_nsegments(sufile))) {
>> +			printk(KERN_WARNING
>> +			       "%s: invalid segment number: %llu\n", __func__,
>> +			       (unsigned long long)sup->sup_segnum);
>> +			nerr++;
>> +		}
>> +	}
>> +	if (nerr > 0) {
>> +		ret = -EINVAL;
>> +		goto out_sem;
>> +	}
> 
> Seems that you can exit from inside the loop:
> 
> 	for (sup = supv; sup < supv + nsup; sup++) {
> 		if (unlikely(sup->sup_segnum >=
> 				nilfs_sufile_get_nsegments(sufile))) {
> 			printk(KERN_WARNING
> 			       "%s: invalid segment number: %llu\n", __func__,
> 			       (unsigned long long)sup->sup_segnum);
> 			ret = -EINVAL;
> 			goto out_sem;
> 		}
> 	}

Yes. I copied that from nilfs_sufile_updatev.

>> +
>> +	sup = supv;
>> +	blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
>> +	ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
>> +	if (ret < 0)
>> +		goto out_sem;
>> +
>> +	for (;;) {
>> +		kaddr = kmap_atomic(bh->b_page);
>> +		su = nilfs_sufile_block_get_segment_usage(
>> +			sufile, sup->sup_segnum, bh, kaddr);
>> +
>> +		if (nilfs_suinfo_update_lastmod(sup))
>> +			su->su_lastmod = cpu_to_le64(sup->sup_sui.sui_lastmod);
>> +
>> +		if (nilfs_suinfo_update_nblocks(sup))
>> +			su->su_nblocks = cpu_to_le32(sup->sup_sui.sui_nblocks);
>> +
>> +		if (nilfs_suinfo_update_flags(sup))
>> +			su->su_flags = cpu_to_le32(sup->sup_sui.sui_flags);
> 
> You must also update the counter value of sh_ncleansegs, sh_ndirtysegs
> in the nilfs_sufile_header struct of sufile header block based on the
> change of these flags.
> 
> In addition, you should ignore NILFS_SEGMENT_USAGE_ACTIVE_FLAG as
> below because this flag is a virtual flag set by running nilfs kernel
> code.  The flag bit should not be written to sufile on disk.
> 
>           (sui_flags & ~(1UL << NILFS_SEGMENT_USAGE_ACTIVE))

Yes. I didn't think of that.

>> +
>> +		kunmap_atomic(kaddr);
>> +
>> +		if (++sup >= supv + nsup)
> 
> You must not use the automatic pointer operation of C language for
> nilfs_suinfo_update because it may be extended in a future release.
> This "++sup" breaks forward compatibility of the ioctl.
> 
> You should do this by:
> 
>                 sup = (void *)sup + supsz;
> 
> Note that pointer type is automatically converted for "void *" type
> variables.


Makes sense. I guess I blindly copied that from nilfs_sufile_updatev,
but with a simple array of __u64 it works of course. With a structure,
that is subject to change, not so much any more.

>> +			break;
>> +		prev_blkoff = blkoff;
>> +		blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
>> +		if (blkoff == prev_blkoff)
>> +			continue;
>> +
>> +		/* get different block */
> 
> You must mark bh that this function changed as dirty with
> mark_buffer_dirty(bh).  Otherwise, the change will be gone.
> 
> 
>> +		brelse(bh);
>> +		ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
>> +		if (unlikely(ret < 0))
>> +			goto out_sem;
>> +	}
>> +	brelse(bh);
>> +
> 
> The sufile should be marked as dirty (if any change happened):
> 
>     nilfs_mdt_mark_dirty(sufile);

Of course. I am sorry that's a really stupid error. I will fix it right
away.

Thanks for your review. I am really embarrassed about all the stupid
avoidable errors.

br,
Andreas Rohner
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Filesystem Development]     [Linux BTRFS]     [Linux CIFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux