static int stat_file(struct kstat *stbuf) { struct file *fd; int rc; fd = filp_open(fname, O_RDONLY, 0); if (IS_ERR(fd)) { pr_err(PREFIX " can't open file %s\n", run_id, fname); return -EIO; } #ifdef HAVE_INODEOPS_ENHANCED_GETATTR rc = vfs_getattr(&fd->f_path, stbuf, STATX_INO, AT_STATX_SYNC_AS_STAT); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) rc = vfs_getattr(&fd->f_path, stbuf); #else rc = vfs_getattr(fd->f_path.mnt, fd->f_path.dentry, stbuf); #endif if (rc != 0) { pr_err(PREFIX " vfs_getattr failed: %d\n", run_id, rc); goto out; } pr_err(PREFIX " inode is %llu\n", run_id, stbuf->ino); rc = 0; out: filp_close(fd, NULL); return rc; }
int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, int flag) { struct path path; int error = -EINVAL; int lookup_flags = 0; if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH)) != 0) goto out; if (!(flag & AT_SYMLINK_NOFOLLOW)) lookup_flags |= LOOKUP_FOLLOW; if (flag & AT_EMPTY_PATH) lookup_flags |= LOOKUP_EMPTY; error = user_path_at(dfd, filename, lookup_flags, &path); if (error) goto out; error = vfs_getattr(path.mnt, path.dentry, stat); if (!error) zpath_realsize(path.dentry, &stat->size); path_put(&path); out: return error; }
/** * ubi_open_volume_path - open UBI volume by its character device node path. * @pathname: volume character device node path * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume the path * to its character device node. */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { int error, ubi_num, vol_id; struct path path; struct kstat stat; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); error = kern_path(pathname, LOOKUP_FOLLOW, &path); if (error) return ERR_PTR(error); error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); path_put(&path); if (error) return ERR_PTR(error); if (!S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); ubi_num = ubi_major2num(MAJOR(stat.rdev)); vol_id = MINOR(stat.rdev) - 1; if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); }
int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, int flag) { struct path path; int error = -EINVAL; unsigned int lookup_flags = 0; if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH)) != 0) goto out; if (!(flag & AT_SYMLINK_NOFOLLOW)) lookup_flags |= LOOKUP_FOLLOW; if (flag & AT_EMPTY_PATH) lookup_flags |= LOOKUP_EMPTY; retry: error = user_path_at(dfd, filename, lookup_flags, &path); if (error) goto out; error = vfs_getattr(&path, stat); path_put(&path); if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } out: return error; }
static int ccfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { int rc = 0; struct dentry *lower_dentry; struct ccfs_inode* inode = ccfs_inode_to_private(dentry->d_inode); struct vfsmount *lower_mnt = ccfs_dentry_to_nested_mnt(dentry); lower_dentry = ccfs_get_nested_dentry(dentry); if ( inode->stat ) { *stat = *inode->stat; return 0; } mutex_lock(&lower_dentry->d_inode->i_mutex); rc = vfs_getattr(lower_mnt, lower_dentry, stat); mutex_unlock(&lower_dentry->d_inode->i_mutex); if ( !rc && inode->cacheable) { inode->stat = kmalloc(sizeof(struct kstat), GFP_KERNEL); if ( inode->stat ) { *(inode->stat) = *stat; } } mdbg(INFO3, "Get stat returned res: %d uid %d gid %d", rc, stat->uid, stat->gid); return rc; }
static int ovl_copy_up_last(struct dentry *dentry, struct iattr *attr, bool no_data) { int err; struct dentry *parent; struct kstat stat; struct path lowerpath; parent = dget_parent(dentry); err = ovl_copy_up(parent); if (err) goto out_dput_parent; ovl_path_lower(dentry, &lowerpath); err = vfs_getattr(&lowerpath, &stat); if (err) goto out_dput_parent; if (no_data) stat.size = 0; err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat, attr); out_dput_parent: dput(parent); return err; }
static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { int err; enum ovl_path_type type; struct path realpath; type = ovl_path_real(dentry, &realpath); err = vfs_getattr(&realpath, stat); if (err) return err; stat->dev = dentry->d_sb->s_dev; stat->ino = dentry->d_inode->i_ino; /* * It's probably not worth it to count subdirs to get the * correct link count. nlink=1 seems to pacify 'find' and * other utilities. */ if (OVL_TYPE_MERGE(type)) stat->nlink = 1; return 0; }
static void fn_open(l4fdx_srv_obj srv_obj, struct internal_request *r) { struct file *f; struct l4fdx_result_t ret; struct l4fdx_client *c = srv_obj->client; int err, fid = -1; char const *path = r->open.path; if (c->basepath) { unsigned l = strlen(path); char *s = kmalloc(c->basepath_len + l + 1, GFP_KERNEL); if (!s) { err = -ENOMEM; goto out; } strncpy(s, c->basepath, c->basepath_len); strncpy(s + c->basepath_len, path, l); s[c->basepath_len + l] = 0; if (!validate_path(s, c->basepath_len + l)) { kfree(s); err = -EINVAL; goto out; } path = s; } call_fdx_event(c, "pre-open", path, UMH_WAIT_PROC); f = filp_open(path, r->open.flags & c->openflags_mask, r->open.mode); if (IS_ERR(f)) { err = PTR_ERR(f); } else { fid = set_free_fdxslot(c, f); if (fid == -1) { filp_close(f, NULL); err = -ENOMEM; } else err = 0; } if (c->flag_nogrow && err == 0) { struct kstat stat; int r = vfs_getattr(&f->f_path, &stat); c->max_file_size = r ? 0 : stat.size; } call_fdx_event(c, "post-open", path, UMH_WAIT_EXEC); if (c->basepath) kfree(path); out: ret.payload.fid = fid; ret.payload.ret = err; res_event(srv_obj, &ret, r->client_req_id); kfree(r); }
extern int vnode_shadow_iop_getattr( struct vfsmount *mnt, DENT_T *dentry, struct kstat *kstat ) { DENT_T *rdentry; VNODE_T *cvp; int err; rdentry = REALDENTRY_LOCKED(dentry, &cvp); if (rdentry == NULL) { err = -EOPNOTSUPP; /* XXX */ } else { VNODE_DGET(rdentry); /* protect inode */ if (rdentry != NULL && rdentry->d_inode != NULL) { err = vfs_getattr(CVN_TO_VFSMNT(cvp), rdentry, kstat); if (err == 0) { SHADOW_CP_INODAT(dentry->d_inode, rdentry->d_inode); } } else err = -EOPNOTSUPP; /* XXX */ VNODE_DPUT(rdentry); REALDENTRY_UNLOCK(dentry, cvp); } return(err); }
static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct path realpath; ovl_path_real(dentry, &realpath); return vfs_getattr(&realpath, stat); }
static int fuse_getattr(const char *path, stat *stbuf) { int res; res = vfs_getattr(path, stbuf); if (res == -1) return -errno; return 0; }
/* Don't inline this: 'struct kstat' is biggish */ static noinline_for_stack long fw_file_size(struct file *file) { struct kstat st; if (vfs_getattr(&file->f_path, &st)) return -1; if (!S_ISREG(st.mode)) return -1; if (st.size != (long)st.size) return -1; return st.size; }
/* Don't inline this: 'struct kstat' is biggish */ static noinline long fw_file_size(struct file *file) { struct kstat st; if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) return -1; if (!S_ISREG(st.mode)) return -1; if (st.size != (long)st.size) return -1; return st.size; }
int vfs_fstat(unsigned int fd, struct kstat *stat) { struct file *f = fget(fd); int error = -EBADF; if (f) { error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); fput(f); } return error; }
int vfs_fstat(unsigned int fd, struct kstat *stat) { struct fd f = fdget_raw(fd); int error = -EBADF; if (f.file) { error = vfs_getattr(&f.file->f_path, stat); fdput(f); } return error; }
int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) { struct nameidata nd; int error; error = __user_walk_fd(dfd, name, 0, &nd); if (!error) { error = vfs_getattr(nd.mnt, nd.dentry, stat); path_release(&nd); } return error; }
int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) { struct path path; int error; error = user_path_at(dfd, name, 0, &path); if (!error) { error = vfs_getattr(path.mnt, path.dentry, stat); path_put(&path); } return error; }
int vfs_fstat(unsigned int fd, struct kstat *stat) { int fput_needed; struct file *f = fget_light(fd, &fput_needed); int error = -EBADF; if (f) { error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); fput_light(f, fput_needed); } return error; }
int devtmpfs_delete_node(struct device *dev) { const char *tmp = NULL; const char *nodename; const struct cred *curr_cred; struct nameidata nd; struct dentry *dentry; struct kstat stat; int deleted = 1; int err; if (!dev_mnt) return 0; nodename = device_get_devnode(dev, NULL, &tmp); if (!nodename) return -ENOMEM; curr_cred = override_creds(&init_cred); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err) goto out; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); if (deleted && strchr(nodename, '/')) delete_path(nodename); out: kfree(tmp); revert_creds(curr_cred); return err; }
unsigned long long file_size(struct file * file_ptr) { struct kstat s; int ret; ret = vfs_getattr(file_ptr->f_path.mnt, file_ptr->f_path.dentry, &s); if (ret != 0) { printk(KERN_ERR "Failed to fstat file\n"); return -1; } return s.size; }
static int handle_remove(const char *nodename, struct device *dev) { struct nameidata nd; struct dentry *dentry; struct kstat stat; int deleted = 1; int err; err = kern_path_parent(nodename, &nd); if (err) return err; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { struct iattr newattrs; /* * before unlinking this node, reset permissions * of possible references like hardlinks */ newattrs.ia_uid = 0; newattrs.ia_gid = 0; newattrs.ia_mode = stat.mode & ~0777; newattrs.ia_valid = ATTR_UID|ATTR_GID|ATTR_MODE; mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs); mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); if (deleted && strchr(nodename, '/')) delete_path(nodename); return err; }
int vfs_fstat(unsigned int fd, struct kstat *stat) { struct file *f; int error = -EBADF; if (scribe_track_next_file_no_inode()) return -ENOMEM; f = fget(fd); if (f) { error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); fput(f); } return error; }
static int diaryfs_getattr(struct vfsmount *mnt, struct dentry * dentry, struct kstat *stat) { int err; struct kstat lower_stat; struct path lower_path; diaryfs_get_lower_path(dentry, &lower_path); err = vfs_getattr(&lower_path, &lower_stat); if (err) goto out; fsstack_copy_attr_all(dentry->d_inode, lower_path.dentry->d_inode); generic_fillattr(dentry->d_inode, stat); stat->blocks = lower_stat.blocks; out: diaryfs_put_lower_path(dentry, &lower_path); return err; }
static int nullfs_vfs_getlowerattr(mount_t mp, struct vfs_attr * vfap, vfs_context_t ctx) { memset(vfap, 0, sizeof(*vfap)); VFSATTR_INIT(vfap); VFSATTR_WANTED(vfap, f_bsize); VFSATTR_WANTED(vfap, f_iosize); VFSATTR_WANTED(vfap, f_blocks); VFSATTR_WANTED(vfap, f_bfree); VFSATTR_WANTED(vfap, f_bavail); VFSATTR_WANTED(vfap, f_bused); VFSATTR_WANTED(vfap, f_files); VFSATTR_WANTED(vfap, f_ffree); VFSATTR_WANTED(vfap, f_capabilities); return vfs_getattr(mp, vfap, ctx); }
/*! 2017. 8.12 study -ing */ static int handle_remove(const char *nodename, struct device *dev) { struct path parent; struct dentry *dentry; int deleted = 0; int err; dentry = kern_path_locked(nodename, &parent); if (IS_ERR(dentry)) return PTR_ERR(dentry); if (dentry->d_inode) { struct kstat stat; struct path p = {.mnt = parent.mnt, .dentry = dentry}; err = vfs_getattr(&p, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { struct iattr newattrs; /* * before unlinking this node, reset permissions * of possible references like hardlinks */ newattrs.ia_uid = GLOBAL_ROOT_UID; newattrs.ia_gid = GLOBAL_ROOT_GID; newattrs.ia_mode = stat.mode & ~0777; newattrs.ia_valid = ATTR_UID|ATTR_GID|ATTR_MODE; mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs, NULL); mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(parent.dentry->d_inode, dentry, NULL); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); mutex_unlock(&parent.dentry->d_inode->i_mutex); path_put(&parent); if (deleted && strchr(nodename, '/')) delete_path(nodename); return err; }
int vfsub_update_h_iattr(struct path *h_path, int *did) { int err; struct kstat st; struct super_block *h_sb; /* for remote fs, leave work for its getattr or d_revalidate */ /* for bad i_attr fs, handle them in aufs_getattr() */ /* still some fs may acquire i_mutex. we need to skip them */ err = 0; if (!did) did = &err; h_sb = h_path->dentry->d_sb; *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb)); if (*did) err = vfs_getattr(h_path->mnt, h_path->dentry, &st); return err; }
/* Wrapper for vfs_getattr() to ensure we have the most * up-to-date inode info if working on a network filesystem. */ int cr_fstat(cr_objectmap_t map, struct file *filp) { struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; char *map_key = 1 + (char *)dentry; int retval = 0; if (!inode->i_op->getattr) { /* Not a special fs, so trivially nothing to do */ } else if (map && cr_find_object(map, map_key, NULL)) { /* Attrs up-to-date, so nothing to do */ } else { struct kstat stat; retval = vfs_getattr(filp->f_vfsmnt, dentry, &stat); if (map && !retval) { cr_insert_object(map, map_key, (void *)1UL, GFP_KERNEL); } } return retval; }
int vfs_fstatat(int dfd, char __user *filename, struct kstat *stat, int flag) { struct path path; int error = -EINVAL; int lookup_flags = 0; if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) goto out; if (!(flag & AT_SYMLINK_NOFOLLOW)) lookup_flags |= LOOKUP_FOLLOW; error = user_path_at(dfd, filename, lookup_flags, &path); if (error) goto out; error = vfs_getattr(path.mnt, path.dentry, stat); path_put(&path); out: return error; }
static struct dentry *ovl_clear_empty(struct dentry *dentry, struct list_head *list) { struct dentry *workdir = ovl_workdir(dentry); struct inode *wdir = workdir->d_inode; struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); struct inode *udir = upperdir->d_inode; struct path upperpath; struct dentry *upper; struct dentry *opaquedir; struct kstat stat; int err; if (WARN_ON(!workdir)) return ERR_PTR(-EROFS); err = ovl_lock_rename_workdir(workdir, upperdir); if (err) goto out; ovl_path_upper(dentry, &upperpath); err = vfs_getattr(&upperpath, &stat); if (err) goto out_unlock; err = -ESTALE; if (!S_ISDIR(stat.mode)) goto out_unlock; upper = upperpath.dentry; if (upper->d_parent->d_inode != udir) goto out_unlock; opaquedir = ovl_lookup_temp(workdir, dentry); err = PTR_ERR(opaquedir); if (IS_ERR(opaquedir)) goto out_unlock; err = ovl_create_real(wdir, opaquedir, &(struct cattr){.mode = stat.mode}, NULL, true);
static int ovl_copy_up_truncate(struct dentry *dentry) { int err; struct dentry *parent; struct kstat stat; struct path lowerpath; parent = dget_parent(dentry); err = ovl_copy_up(parent); if (err) goto out_dput_parent; ovl_path_lower(dentry, &lowerpath); err = vfs_getattr(&lowerpath, &stat); if (err) goto out_dput_parent; stat.size = 0; err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); out_dput_parent: dput(parent); return err; }