mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 12:21:22 -05:00
fanotify: report file range info with pre-content events
With group class FAN_CLASS_PRE_CONTENT, report offset and length info along with FAN_PRE_ACCESS pre-content events. This information is meant to be used by hierarchical storage managers that want to fill partial content of files on first access to range. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/b90a9e6c809dd3cad5684da90f23ea93ec6ce8c8.1731684329.git.josef@toxicpanda.com
This commit is contained in:
@@ -448,6 +448,14 @@ static inline bool fanotify_is_perm_event(u32 mask)
|
||||
mask & FANOTIFY_PERM_EVENTS;
|
||||
}
|
||||
|
||||
static inline bool fanotify_event_has_access_range(struct fanotify_event *event)
|
||||
{
|
||||
if (!(event->mask & FANOTIFY_PRE_CONTENT_EVENTS))
|
||||
return false;
|
||||
|
||||
return FANOTIFY_PERM(event)->ppos;
|
||||
}
|
||||
|
||||
static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
|
||||
{
|
||||
return container_of(fse, struct fanotify_event, fse);
|
||||
|
||||
@@ -121,6 +121,8 @@ struct kmem_cache *fanotify_perm_event_cachep __ro_after_init;
|
||||
sizeof(struct fanotify_event_info_pidfd)
|
||||
#define FANOTIFY_ERROR_INFO_LEN \
|
||||
(sizeof(struct fanotify_event_info_error))
|
||||
#define FANOTIFY_RANGE_INFO_LEN \
|
||||
(sizeof(struct fanotify_event_info_range))
|
||||
|
||||
static int fanotify_fid_info_len(int fh_len, int name_len)
|
||||
{
|
||||
@@ -180,6 +182,9 @@ static size_t fanotify_event_len(unsigned int info_mode,
|
||||
if (info_mode & FAN_REPORT_PIDFD)
|
||||
event_len += FANOTIFY_PIDFD_INFO_LEN;
|
||||
|
||||
if (fanotify_event_has_access_range(event))
|
||||
event_len += FANOTIFY_RANGE_INFO_LEN;
|
||||
|
||||
return event_len;
|
||||
}
|
||||
|
||||
@@ -516,6 +521,30 @@ static int copy_pidfd_info_to_user(int pidfd,
|
||||
return info_len;
|
||||
}
|
||||
|
||||
static size_t copy_range_info_to_user(struct fanotify_event *event,
|
||||
char __user *buf, int count)
|
||||
{
|
||||
struct fanotify_perm_event *pevent = FANOTIFY_PERM(event);
|
||||
struct fanotify_event_info_range info = { };
|
||||
size_t info_len = FANOTIFY_RANGE_INFO_LEN;
|
||||
|
||||
if (WARN_ON_ONCE(info_len > count))
|
||||
return -EFAULT;
|
||||
|
||||
if (WARN_ON_ONCE(!pevent->ppos))
|
||||
return -EINVAL;
|
||||
|
||||
info.hdr.info_type = FAN_EVENT_INFO_TYPE_RANGE;
|
||||
info.hdr.len = info_len;
|
||||
info.offset = *(pevent->ppos);
|
||||
info.count = pevent->count;
|
||||
|
||||
if (copy_to_user(buf, &info, info_len))
|
||||
return -EFAULT;
|
||||
|
||||
return info_len;
|
||||
}
|
||||
|
||||
static int copy_info_records_to_user(struct fanotify_event *event,
|
||||
struct fanotify_info *info,
|
||||
unsigned int info_mode, int pidfd,
|
||||
@@ -637,6 +666,15 @@ static int copy_info_records_to_user(struct fanotify_event *event,
|
||||
total_bytes += ret;
|
||||
}
|
||||
|
||||
if (fanotify_event_has_access_range(event)) {
|
||||
ret = copy_range_info_to_user(event, buf, count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
buf += ret;
|
||||
count -= ret;
|
||||
total_bytes += ret;
|
||||
}
|
||||
|
||||
return total_bytes;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ struct fanotify_event_metadata {
|
||||
#define FAN_EVENT_INFO_TYPE_DFID 3
|
||||
#define FAN_EVENT_INFO_TYPE_PIDFD 4
|
||||
#define FAN_EVENT_INFO_TYPE_ERROR 5
|
||||
#define FAN_EVENT_INFO_TYPE_RANGE 6
|
||||
|
||||
/* Special info types for FAN_RENAME */
|
||||
#define FAN_EVENT_INFO_TYPE_OLD_DFID_NAME 10
|
||||
@@ -192,6 +193,13 @@ struct fanotify_event_info_error {
|
||||
__u32 error_count;
|
||||
};
|
||||
|
||||
struct fanotify_event_info_range {
|
||||
struct fanotify_event_info_header hdr;
|
||||
__u32 pad;
|
||||
__u64 offset;
|
||||
__u64 count;
|
||||
};
|
||||
|
||||
/*
|
||||
* User space may need to record additional information about its decision.
|
||||
* The extra information type records what kind of information is included.
|
||||
|
||||
Reference in New Issue
Block a user