[Devel] Re: [PATCH] Rework /proc/locks via seq_files and seq_list helpers

Pavel Emelyanov xemul at openvz.org
Thu Sep 20 01:27:32 PDT 2007


J. Bruce Fields wrote:
> On Wed, Sep 19, 2007 at 03:35:27PM +0400, Pavel Emelyanov wrote:
>> Currently /proc/locks is shown with a proc_read function, but
>> its behavior is rather complex as it has to manually handle
>> current offset and buffer length. On the other hand, files 
>> that show objects from lists can be easily reimplemented using
>> the sequential files and the seq_list_XXX() helpers.
>>
>> This saves (as usually) 16 lines of code and more than 200 from
>> the .text section.
>>
>> This patch looks rather ugly, as diff often uses curly braces
>> as not-changed lines, but I haven't managed to organize the 
>> code to make diff look better. Except for move the whole proc
>> related stuff upper/lower in the locks.c file...
> 
> Fine by me.  I've lost track--are you assuming some earlier patches are
> applied?  It doesn't seem to apply to any copy of locks.c I have.

Yes, this applies the the set of patches that cleanup the 
MANDATORY_LOCK macro (5 patches just accepted by Andrew).

> --b.
> 
>> Signed-off-by: Pavel Emelyanov <xemul at openvz.org>
>>
>> ---
>>
>>  fs/locks.c          |  124 ++++++++++++++++++++++------------------------------
>>  fs/proc/proc_misc.c |   20 ++++----
>>  2 files changed, 64 insertions(+), 80 deletions(-)
>>
>> diff --git a/fs/locks.c b/fs/locks.c
>> index 8e849ed..746dc70 100644
>> --- a/fs/locks.c
>> +++ b/fs/locks.c
>> @@ -2032,134 +2032,116 @@ int vfs_cancel_lock(struct file *filp, s
>>  
>>  EXPORT_SYMBOL_GPL(vfs_cancel_lock);
>>  
>> -static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
>> +#ifdef CONFIG_PROC_FS
>> +#include <linux/seq_file.h>
>> +
>> +static void lock_get_status(struct seq_file *f, struct file_lock *fl,
>> +							int id, char *pfx)
>>  {
>>  	struct inode *inode = NULL;
>>  
>>  	if (fl->fl_file != NULL)
>>  		inode = fl->fl_file->f_path.dentry->d_inode;
>>  
>> -	out += sprintf(out, "%d:%s ", id, pfx);
>> +	seq_printf(f, "%d:%s ", id, pfx);
>>  	if (IS_POSIX(fl)) {
>> -		out += sprintf(out, "%6s %s ",
>> +		seq_printf(f, "%6s %s ",
>>  			     (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
>>  			     (inode == NULL) ? "*NOINODE*" :
>>  			     mandatory_lock(inode) ? "MANDATORY" : "ADVISORY ");
>>  	} else if (IS_FLOCK(fl)) {
>>  		if (fl->fl_type & LOCK_MAND) {
>> -			out += sprintf(out, "FLOCK  MSNFS     ");
>> +			seq_printf(f, "FLOCK  MSNFS     ");
>>  		} else {
>> -			out += sprintf(out, "FLOCK  ADVISORY  ");
>> +			seq_printf(f, "FLOCK  ADVISORY  ");
>>  		}
>>  	} else if (IS_LEASE(fl)) {
>> -		out += sprintf(out, "LEASE  ");
>> +		seq_printf(f, "LEASE  ");
>>  		if (fl->fl_type & F_INPROGRESS)
>> -			out += sprintf(out, "BREAKING  ");
>> +			seq_printf(f, "BREAKING  ");
>>  		else if (fl->fl_file)
>> -			out += sprintf(out, "ACTIVE    ");
>> +			seq_printf(f, "ACTIVE    ");
>>  		else
>> -			out += sprintf(out, "BREAKER   ");
>> +			seq_printf(f, "BREAKER   ");
>>  	} else {
>> -		out += sprintf(out, "UNKNOWN UNKNOWN  ");
>> +		seq_printf(f, "UNKNOWN UNKNOWN  ");
>>  	}
>>  	if (fl->fl_type & LOCK_MAND) {
>> -		out += sprintf(out, "%s ",
>> +		seq_printf(f, "%s ",
>>  			       (fl->fl_type & LOCK_READ)
>>  			       ? (fl->fl_type & LOCK_WRITE) ? "RW   " : "READ "
>>  			       : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE ");
>>  	} else {
>> -		out += sprintf(out, "%s ",
>> +		seq_printf(f, "%s ",
>>  			       (fl->fl_type & F_INPROGRESS)
>>  			       ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ "
>>  			       : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ ");
>>  	}
>>  	if (inode) {
>>  #ifdef WE_CAN_BREAK_LSLK_NOW
>> -		out += sprintf(out, "%d %s:%ld ", fl->fl_pid,
>> +		seq_printf(f, "%d %s:%ld ", fl->fl_pid,
>>  				inode->i_sb->s_id, inode->i_ino);
>>  #else
>>  		/* userspace relies on this representation of dev_t ;-( */
>> -		out += sprintf(out, "%d %02x:%02x:%ld ", fl->fl_pid,
>> +		seq_printf(f, "%d %02x:%02x:%ld ", fl->fl_pid,
>>  				MAJOR(inode->i_sb->s_dev),
>>  				MINOR(inode->i_sb->s_dev), inode->i_ino);
>>  #endif
>>  	} else {
>> -		out += sprintf(out, "%d <none>:0 ", fl->fl_pid);
>> +		seq_printf(f, "%d <none>:0 ", fl->fl_pid);
>>  	}
>>  	if (IS_POSIX(fl)) {
>>  		if (fl->fl_end == OFFSET_MAX)
>> -			out += sprintf(out, "%Ld EOF\n", fl->fl_start);
>> +			seq_printf(f, "%Ld EOF\n", fl->fl_start);
>>  		else
>> -			out += sprintf(out, "%Ld %Ld\n", fl->fl_start,
>> -					fl->fl_end);
>> +			seq_printf(f, "%Ld %Ld\n", fl->fl_start, fl->fl_end);
>>  	} else {
>> -		out += sprintf(out, "0 EOF\n");
>> +		seq_printf(f, "0 EOF\n");
>>  	}
>>  }
>>  
>> -static void move_lock_status(char **p, off_t* pos, off_t offset)
>> +static int locks_show(struct seq_file *f, void *v)
>>  {
>> -	int len;
>> -	len = strlen(*p);
>> -	if(*pos >= offset) {
>> -		/* the complete line is valid */
>> -		*p += len;
>> -		*pos += len;
>> -		return;
>> -	}
>> -	if(*pos+len > offset) {
>> -		/* use the second part of the line */
>> -		int i = offset-*pos;
>> -		memmove(*p,*p+i,len-i);
>> -		*p += len-i;
>> -		*pos += len;
>> -		return;
>> -	}
>> -	/* discard the complete line */
>> -	*pos += len;
>> -}
>> +	int idx;
>> +	struct file_lock *fl, *bfl;
>>  
>> -/**
>> - *	get_locks_status	-	reports lock usage in /proc/locks
>> - *	@buffer: address in userspace to write into
>> - *	@start: ?
>> - *	@offset: how far we are through the buffer
>> - *	@length: how much to read
>> - */
>> +	fl = list_entry(v, struct file_lock, fl_link);
>> +	idx = (int)f->private;
>>  
>> -int get_locks_status(char *buffer, char **start, off_t offset, int length)
>> -{
>> -	struct file_lock *fl;
>> -	char *q = buffer;
>> -	off_t pos = 0;
>> -	int i = 0;
>> +	lock_get_status(f, fl, idx, "");
>>  
>> -	lock_kernel();
>> -	list_for_each_entry(fl, &file_lock_list, fl_link) {
>> -		struct file_lock *bfl;
>> +	list_for_each_entry(bfl, &fl->fl_block, fl_block)
>> +		lock_get_status(f, bfl, idx, " ->");
>>  
>> -		lock_get_status(q, fl, ++i, "");
>> -		move_lock_status(&q, &pos, offset);
>> +	f->private = (void *)(idx + 1);
>> +	return 0;
>> +}
>>  
>> -		if(pos >= offset+length)
>> -			goto done;
>> +static void *locks_start(struct seq_file *f, loff_t *pos)
>> +{
>> +	lock_kernel();
>> +	f->private = (void *)1;
>> +	return seq_list_start(&file_lock_list, *pos);
>> +}
>>  
>> -		list_for_each_entry(bfl, &fl->fl_block, fl_block) {
>> -			lock_get_status(q, bfl, i, " ->");
>> -			move_lock_status(&q, &pos, offset);
>> +static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
>> +{
>> +	return seq_list_next(v, &file_lock_list, pos);
>> +}
>>  
>> -			if(pos >= offset+length)
>> -				goto done;
>> -		}
>> -	}
>> -done:
>> +static void locks_stop(struct seq_file *f, void *v)
>> +{
>>  	unlock_kernel();
>> -	*start = buffer;
>> -	if(q-buffer < length)
>> -		return (q-buffer);
>> -	return length;
>>  }
>>  
>> +struct seq_operations locks_seq_operations = {
>> +	.start	= locks_start,
>> +	.next	= locks_next,
>> +	.stop	= locks_stop,
>> +	.show	= locks_show,
>> +};
>> +#endif
>> +
>>  /**
>>   *	lock_may_read - checks that the region is free of locks
>>   *	@inode: the inode that is being read
>> diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
>> index 166a6db..043621c 100644
>> --- a/fs/proc/proc_misc.c
>> +++ b/fs/proc/proc_misc.c
>> @@ -68,7 +68,6 @@ extern int get_stram_list(char *);
>>  extern int get_filesystem_list(char *);
>>  extern int get_exec_domain_list(char *);
>>  extern int get_dma_list(char *);
>> -extern int get_locks_status (char *, char **, off_t, int);
>>  
>>  static int proc_calc_metrics(char *page, char **start, off_t off,
>>  				 int count, int *eof, int len)
>> @@ -630,16 +629,19 @@ static int cmdline_read_proc(char *page,
>>  	return proc_calc_metrics(page, start, off, count, eof, len);
>>  }
>>  
>> -static int locks_read_proc(char *page, char **start, off_t off,
>> -				 int count, int *eof, void *data)
>> +extern struct seq_operations locks_seq_operations;
>> +static int locks_open(struct inode *inode, struct file *filp)
>>  {
>> -	int len = get_locks_status(page, start, off, count);
>> -
>> -	if (len < count)
>> -		*eof = 1;
>> -	return len;
>> +	return seq_open(filp, &locks_seq_operations);
>>  }
>>  
>> +static const struct file_operations proc_locks_operations = {
>> +	.open		= locks_open,
>> +	.read		= seq_read,
>> +	.llseek		= seq_lseek,
>> +	.release	= seq_release,
>> +};
>> +
>>  static int execdomains_read_proc(char *page, char **start, off_t off,
>>  				 int count, int *eof, void *data)
>>  {
>> @@ -916,7 +918,6 @@ void __init proc_misc_init(void)
>>  #endif
>>  		{"filesystems",	filesystems_read_proc},
>>  		{"cmdline",	cmdline_read_proc},
>> -		{"locks",	locks_read_proc},
>>  		{"execdomains",	execdomains_read_proc},
>>  		{NULL,}
>>  	};
>> @@ -934,6 +935,7 @@ void __init proc_misc_init(void)
>>  			entry->proc_fops = &proc_kmsg_operations;
>>  	}
>>  #endif
>> +	create_seq_entry("locks", 0, &proc_locks_operations);
>>  	create_seq_entry("devices", 0, &proc_devinfo_operations);
>>  	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
>>  #ifdef CONFIG_BLOCK
> 




More information about the Devel mailing list