2519 lines · 56.8 KB · C
RawDownload
int proc_dointvec_minmax(struct ctl_table *table, int write,		  void __user *buffer, size_t *lenp, loff_t *ppos){	struct do_proc_dointvec_minmax_conv_param param = {		.min = (int *) table->extra1,		.max = (int *) table->extra2,	};	return do_proc_dointvec(table, write, buffer, lenp, ppos,				do_proc_dointvec_minmax_conv, &param);} static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,				     void __user *buffer,				     size_t *lenp, loff_t *ppos,				     unsigned long convmul,				     unsigned long convdiv){	unsigned long *i, *min, *max;	int vleft, first = 1, err = 0;	unsigned long page = 0;	size_t left;	char *kbuf; 	if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {		*lenp = 0;		return 0;	} 	i = (unsigned long *) data;	min = (unsigned long *) table->extra1;	max = (unsigned long *) table->extra2;	vleft = table->maxlen / sizeof(unsigned long);	left = *lenp; 	if (write) {		if (left > PAGE_SIZE - 1)			left = PAGE_SIZE - 1;		page = __get_free_page(GFP_TEMPORARY);		kbuf = (char *) page;		if (!kbuf)			return -ENOMEM;		if (copy_from_user(kbuf, buffer, left)) {			err = -EFAULT;			goto free;		}		kbuf[left] = 0;	} 	for (; left && vleft--; i++, first = 0) {		unsigned long val; 		if (write) {			bool neg; 			left -= proc_skip_spaces(&kbuf); 			err = proc_get_long(&kbuf, &left, &val, &neg,					     proc_wspace_sep,					     sizeof(proc_wspace_sep), NULL);			if (err)				break;			if (neg)				continue;			if ((min && val < *min) || (max && val > *max))				continue;			*i = val;		} else {			val = convdiv * (*i) / convmul;			if (!first)				err = proc_put_char(&buffer, &left, '\t');			err = proc_put_long(&buffer, &left, val, false);			if (err)				break;		}	} 	if (!write && !first && left && !err)		err = proc_put_char(&buffer, &left, '\n');	if (write && !err)		left -= proc_skip_spaces(&kbuf);free:	if (write) {		free_page(page);		if (first)			return err ? : -EINVAL;	}	*lenp -= left;	*ppos += *lenp;	return err;} static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,				     void __user *buffer,				     size_t *lenp, loff_t *ppos,				     unsigned long convmul,				     unsigned long convdiv){	return __do_proc_doulongvec_minmax(table->data, table, write,			buffer, lenp, ppos, convmul, convdiv);} /** * proc_doulongvec_minmax - read a vector of long integers with min/max values * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: file position * * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long * values from/to the user buffer, treated as an ASCII string. * * This routine will ensure the values are within the range specified by * table->extra1 (min) and table->extra2 (max). * * Returns 0 on success. */int proc_doulongvec_minmax(struct ctl_table *table, int write,			   void __user *buffer, size_t *lenp, loff_t *ppos){    return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);} /** * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: file position * * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long * values from/to the user buffer, treated as an ASCII string. The values * are treated as milliseconds, and converted to jiffies when they are stored. * * This routine will ensure the values are within the range specified by * table->extra1 (min) and table->extra2 (max). * * Returns 0 on success. */int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,				      void __user *buffer,				      size_t *lenp, loff_t *ppos){    return do_proc_doulongvec_minmax(table, write, buffer,				     lenp, ppos, HZ, 1000l);}  static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,					 int *valp,					 int write, void *data){	if (write) {		if (*lvalp > LONG_MAX / HZ)			return 1;		*valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);	} else {		int val = *valp;		unsigned long lval;		if (val < 0) {			*negp = true;			lval = (unsigned long)-val;		} else {			*negp = false;			lval = (unsigned long)val;		}		*lvalp = lval / HZ;	}	return 0;} static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,						int *valp,						int write, void *data){	if (write) {		if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)			return 1;		*valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);	} else {		int val = *valp;		unsigned long lval;		if (val < 0) {			*negp = true;			lval = (unsigned long)-val;		} else {			*negp = false;			lval = (unsigned long)val;		}		*lvalp = jiffies_to_clock_t(lval);	}	return 0;} static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,					    int *valp,					    int write, void *data){	if (write) {		*valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);	} else {		int val = *valp;		unsigned long lval;		if (val < 0) {			*negp = true;			lval = (unsigned long)-val;		} else {			*negp = false;			lval = (unsigned long)val;		}		*lvalp = jiffies_to_msecs(lval);	}	return 0;} /** * proc_dointvec_jiffies - read a vector of integers as seconds * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: file position * * Reads/writes up to table->maxlen/sizeof(unsigned int) integer * values from/to the user buffer, treated as an ASCII string.  * The values read are assumed to be in seconds, and are converted into * jiffies. * * Returns 0 on success. */int proc_dointvec_jiffies(struct ctl_table *table, int write,			  void __user *buffer, size_t *lenp, loff_t *ppos){    return do_proc_dointvec(table,write,buffer,lenp,ppos,		    	    do_proc_dointvec_jiffies_conv,NULL);} /** * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: pointer to the file position * * Reads/writes up to table->maxlen/sizeof(unsigned int) integer * values from/to the user buffer, treated as an ASCII string.  * The values read are assumed to be in 1/USER_HZ seconds, and  * are converted into jiffies. * * Returns 0 on success. */int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,				 void __user *buffer, size_t *lenp, loff_t *ppos){    return do_proc_dointvec(table,write,buffer,lenp,ppos,		    	    do_proc_dointvec_userhz_jiffies_conv,NULL);} /** * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: file position * @ppos: the current position in the file * * Reads/writes up to table->maxlen/sizeof(unsigned int) integer * values from/to the user buffer, treated as an ASCII string.  * The values read are assumed to be in 1/1000 seconds, and  * are converted into jiffies. * * Returns 0 on success. */int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,			     void __user *buffer, size_t *lenp, loff_t *ppos){	return do_proc_dointvec(table, write, buffer, lenp, ppos,				do_proc_dointvec_ms_jiffies_conv, NULL);} static int proc_do_cad_pid(struct ctl_table *table, int write,			   void __user *buffer, size_t *lenp, loff_t *ppos){	struct pid *new_pid;	pid_t tmp;	int r; 	tmp = pid_vnr(cad_pid); 	r = __do_proc_dointvec(&tmp, table, write, buffer,			       lenp, ppos, NULL, NULL);	if (r || !write)		return r; 	new_pid = find_get_pid(tmp);	if (!new_pid)		return -ESRCH; 	put_pid(xchg(&cad_pid, new_pid));	return 0;} /** * proc_do_large_bitmap - read/write from/to a large bitmap * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: file position * * The bitmap is stored at table->data and the bitmap length (in bits) * in table->maxlen. * * We use a range comma separated format (e.g. 1,3-4,10-10) so that * large bitmaps may be represented in a compact manner. Writing into * the file will clear the bitmap then update it with the given input. * * Returns 0 on success. */int proc_do_large_bitmap(struct ctl_table *table, int write,			 void __user *buffer, size_t *lenp, loff_t *ppos){	int err = 0;	bool first = 1;	size_t left = *lenp;	unsigned long bitmap_len = table->maxlen;	unsigned long *bitmap = (unsigned long *) table->data;	unsigned long *tmp_bitmap = NULL;	char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c; 	if (!bitmap_len || !left || (*ppos && !write)) {		*lenp = 0;		return 0;	} 	if (write) {		unsigned long page = 0;		char *kbuf; 		if (left > PAGE_SIZE - 1)			left = PAGE_SIZE - 1; 		page = __get_free_page(GFP_TEMPORARY);		kbuf = (char *) page;		if (!kbuf)			return -ENOMEM;		if (copy_from_user(kbuf, buffer, left)) {			free_page(page);			return -EFAULT;                }		kbuf[left] = 0; 		tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),				     GFP_KERNEL);		if (!tmp_bitmap) {			free_page(page);			return -ENOMEM;		}		proc_skip_char(&kbuf, &left, '\n');		while (!err && left) {			unsigned long val_a, val_b;			bool neg; 			err = proc_get_long(&kbuf, &left, &val_a, &neg, tr_a,					     sizeof(tr_a), &c);			if (err)				break;			if (val_a >= bitmap_len || neg) {				err = -EINVAL;				break;			} 			val_b = val_a;			if (left) {				kbuf++;				left--;			} 			if (c == '-') {				err = proc_get_long(&kbuf, &left, &val_b,						     &neg, tr_b, sizeof(tr_b),						     &c);				if (err)					break;				if (val_b >= bitmap_len || neg ||				    val_a > val_b) {					err = -EINVAL;					break;				}				if (left) {					kbuf++;					left--;				}			} 			bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);			first = 0;			proc_skip_char(&kbuf, &left, '\n');		}		free_page(page);	} else {		unsigned long bit_a, bit_b = 0; 		while (left) {			bit_a = find_next_bit(bitmap, bitmap_len, bit_b);			if (bit_a >= bitmap_len)				break;			bit_b = find_next_zero_bit(bitmap, bitmap_len,						   bit_a + 1) - 1; 			if (!first) {				err = proc_put_char(&buffer, &left, ',');				if (err)					break;			}			err = proc_put_long(&buffer, &left, bit_a, false);			if (err)				break;			if (bit_a != bit_b) {				err = proc_put_char(&buffer, &left, '-');				if (err)					break;				err = proc_put_long(&buffer, &left, bit_b, false);				if (err)					break;			} 			first = 0; bit_b++;		}		if (!err)			err = proc_put_char(&buffer, &left, '\n');	} 	if (!err) {		if (write) {			if (*ppos)				bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);			else				bitmap_copy(bitmap, tmp_bitmap, bitmap_len);		}		kfree(tmp_bitmap);		*lenp -= left;		*ppos += *lenp;		return 0;	} else {		kfree(tmp_bitmap);		return err;	}} #else /* CONFIG_PROC_SYSCTL */ int proc_dostring(struct ctl_table *table, int write,		  void __user *buffer, size_t *lenp, loff_t *ppos){	return -ENOSYS;} int proc_dointvec(struct ctl_table *table, int write,		  void __user *buffer, size_t *lenp, loff_t *ppos){	return -ENOSYS;} int proc_dointvec_minmax(struct ctl_table *table, int write,		    void __user *buffer, size_t *lenp, loff_t *ppos){	return -ENOSYS;} int proc_dointvec_jiffies(struct ctl_table *table, int write,		    void __user *buffer, size_t *lenp, loff_t *ppos){	return -ENOSYS;} int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,		    void __user *buffer, size_t *lenp, loff_t *ppos){	return -ENOSYS;} int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,			     void __user *buffer, size_t *lenp, loff_t *ppos){	return -ENOSYS;} int proc_doulongvec_minmax(struct ctl_table *table, int write,		    void __user *buffer, size_t *lenp, loff_t *ppos){	return -ENOSYS;} int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,				      void __user *buffer,				      size_t *lenp, loff_t *ppos)

Lines 2001–2500 of 2519. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t